library(tidyverse)
library(forecast)
library(tseries)
library(ggplot2)
library(gridExtra)
library(knitr)
library(kableExtra)
library(plotly)
library(lubridate)
library(quantmod)
library(fpp2)
library(scales)
library(viridis)
library(patchwork)
library(grid)
library(RColorBrewer)
library(dplyr)
# Tema personalizado elegante
theme_professional <- function() {
  theme_minimal() +
  theme(
    plot.background = element_rect(fill = "white", color = NA),
    panel.background = element_rect(fill = "#f8f9fa", color = NA),
    panel.grid.major = element_line(color = "#e2e8f0", size = 0.4),
    panel.grid.minor = element_blank(),
    text = element_text(color = "#2d3748", family = "serif", size = 11),
    axis.text = element_text(color = "#4a5568", size = 10),
    axis.title = element_text(color = "#1a365d", face = "bold", size = 12),
    plot.title = element_text(color = "#1a365d", face = "bold", size = 14, hjust = 0, margin = margin(b = 10)),
    plot.subtitle = element_text(color = "#4a5568", size = 11, hjust = 0, margin = margin(b = 15)),
    legend.background = element_rect(fill = "white", color = NA),
    legend.text = element_text(color = "#4a5568", size = 10),
    legend.title = element_text(color = "#1a365d", face = "bold", size = 10),
    legend.position = "bottom"
  )
}

theme_set(theme_professional())

1 Introducción

Los mercados de metales preciosos constituyen componentes esenciales de la economía global cuya dinámica responde a múltiples factores interconectados: ciclos económicos, expectativas inflacionarias, volatilidad de sistemas financieros, demanda sectorial (manufactura, electrónica, automoción, joyería) y restricciones de oferta minera amplificadas por tensiones geopolíticas. El ETF GLTR (abrdn Physical Precious Metals Basket Shares) proporciona exposición diversificada a cuatro metales preciosos: oro, plata, platino y paladio, cuya correlación con ciclos macroeconómicos varía según el metal y el contexto. Esta composición lo posiciona como indicador agregado sensible de la salud de mercados de commodities y proxy de demanda por activos refugio durante episodios de inestabilidad financiera o depreciación de monedas.

El análisis de series temporales es indispensable para decodificar esta complejidad. Permite:

  1. Identificar tendencias estructurales de mediano y largo plazo subyacentes a fluctuaciones de corto plazo.
  2. Detectar y cuantificar patrones estacionales y componentes cíclicos.
  3. Reconocer puntos de quiebre que señalan cambios en condiciones de equilibrio de mercado.
  4. Medir la evolución de la volatilidad para calibración de riesgo.
  5. Generar pronósticos probabilísticos que orienten decisiones de inversión y gestión de exposiciones en contextos de incertidumbre persistente. Este tipo de análisis trasciende el interés puramente financiero. Para inversores, la precisión predictiva sobre GLTR mejora estrategias de diversificación y cobertura de riesgos sistémicos. Para gestores de riesgos en instituciones financieras, estos pronósticos alimentan modelos de pérdidas potenciales, pruebas de estrés y cálculos de requerimientos de capital. Para autoridades monetarias y bancos centrales, la dinámica de metales preciosos proporciona señales tempranas sobre presiones inflacionarias, credibilidad de políticas monetarias y cambios en expectativas de inversores globales. En síntesis, la capacidad de anticipar cambios en mercados de materias primas es crítica para la estabilidad financiera y prevención de crisis en contextos de creciente incertidumbre global.

1.1 Relevancia del Análisis

📊 Importancia del Análisis ARIMA

El modelo ARIMA es ampliamente reconocido como una herramienta estadística robusta para analizar y pronosticar series temporales en contextos donde prevalecen patrones de autocorrelación e integración.

En esta sección exploraremos los fundamentos teóricos y la aplicación práctica del modelo ARIMA utilizando datos del OECD Data Explorer, permitiendo una comprensión profunda de la estructura temporal de nuestros datos y generando pronósticos confiables para el análisis futuro.

2 Metodología

2.1 Concepto de Serie de Tiempo

Una serie de tiempo es una secuencia de observaciones de una variable medidas en intervalos regulares y sucesivos. Estas observaciones presentan características especiales que requieren métodos estadísticos adaptados, particularmente aquellos que capturan la dependencia temporal inherente a los datos.

2.1.1 Componentes Fundamentales

\[Y_t = T_t + S_t + C_t + I_t\]

Donde cada componente representa:

  • \(Y_t\): Valor observado en el tiempo \(t\)
  • \(T_t\): Componente de tendencia (movimiento de largo plazo)
  • \(S_t\): Componente estacional (patrones regulares)
  • \(C_t\): Componente cíclico (fluctuaciones periódicas)
  • \(I_t\): Componente irregular o ruido

2.2 Modelo ARIMA

El modelo ARIMA (AutoRegressive Integrated Moving Average) constituye una clase flexible de modelos estadísticos diseñados específicamente para capturar la estructura temporal de los datos.

2.2.1 Estructura ARIMA(p, d, q)

El modelo se compone de tres elementos:

1. AR(p) - Autorregresivo: \[Y_t = c + \phi_1 Y_{t-1} + \phi_2 Y_{t-2} + \cdots + \phi_p Y_{t-p} + \epsilon_t\]

2. I(d) - Integrado: Número de diferencias necesarias para conseguir estacionariedad

3. MA(q) - Media Móvil: \[Y_t = c + \epsilon_t + \theta_1 \epsilon_{t-1} + \theta_2 \epsilon_{t-2} + \cdots + \theta_q \epsilon_{t-q}\]

2.2.2 Ventajas Metodológicas

Características del Modelo ARIMA:

  • Captura patrones complejos de autocorrelación
  • Flexible para diferentes estructuras de datos
  • Ampliamente validado en literatura académica
  • Genera pronósticos confiables a corto-mediano plazo
  • Fundamentado en teoría estadística sólida

3 Descripción

— Carga y Preparación—-

AccionesEX <- getSymbols("GLTR", src = "yahoo", auto.assign = FALSE, 
                         from = "2022-10-31")

names(AccionesEX)
## [1] "GLTR.Open"     "GLTR.High"     "GLTR.Low"      "GLTR.Close"   
## [5] "GLTR.Volume"   "GLTR.Adjusted"
GLTR <- AccionesEX$GLTR.Close

# Preparar dataframe para análisis descriptivo
GLTR_df <- data.frame(
  Fecha = index(GLTR),
  Precio = as.numeric(GLTR),
  Año = year(index(GLTR)),
  Mes = month(index(GLTR), label = TRUE, abbr = FALSE),
  Dia_Semana = wday(index(GLTR), label = TRUE, abbr = FALSE)
)

3.1 Descripción de la serie

###Ficha técnica

El abrdn Physical Precious Metals Basket Shares ETF (GLTR) es un fondo cotizado en bolsa que busca replicar el comportamiento conjunto de una canasta de metales preciosos físicos, integrada principalmente por oro, plata, platino y paladio. Fue lanzado en octubre de 2010, en un contexto posterior a la crisis financiera global de 2008–2009, cuando se intensificó el interés de los inversionistas por activos refugio y vehículos que ofrecieran exposición directa a metales sin necesidad de almacenar lingotes de forma individual. GLTR está estructurado como un grantor trust respaldado por lingotes físicos, custodiados en bóvedas certificadas en centros financieros como Londres y Zúrich. Esta configuración evita riesgos asociados a derivados y contratos de futuros, vinculando el valor del fondo directamente a los precios spot de los metales subyacentes. El activo bajo gestión asciende a aproximadamente 1.850 millones de USD, validando su relevancia y liquidez en los mercados institucionales y de retail.

# Crear tabla comparativa estilo profesional
ficha_tecnica <- data.frame(
  Característica = c(
    "Nombre del ETF",
    "Símbolo/Ticker",
    "Tipo de activo",
    "Activos subyacentes",
    "Composición actual",
    "Activos bajo gestión (AUM)",
    "Expense Ratio",
    "Beta (vs. S&P 500)",
    "Rango 52 semanas",
    "Precio actual (aprox)",
    "Rendimiento 2024",
    "Rendimiento YTD 2025",
    "Volumen promedio diario",
    "Bolsa de cotización",
    "Fecha de lanzamiento"
  ),
  Valor = c(
    "Aberdeen Standard Physical Precious Metals Basket Shares ETF",
    "GLTR",
    "ETF de metales preciosos físicos",
    "Oro, plata, paladio, platino físicos",
    "Oro: 62%, Plata: 31%, Paladio: 4%, Platino: 3%",
    "$1,850 millones USD",
    "0.60%",
    "0.21",
    "$109.20 - $171.85",
    "$168.50",
    "+20.3%",
    "+38.5% (hasta octubre)",
    "150,000 acciones",
    "NYSE Arca",
    "Octubre 2010"
  ),
  Nota = c(
    "Nombre completo del instrumento",
    "Ticker de negociación principal",
    "Clasificación del producto",
    "Metales físicos almacenados en bóvedas",
    "Distribución basada en valores de mercado actuales",
    "Ha crecido 35% en los últimos 12 meses",
    "Competitivo dentro del sector de ETFs de metales",
    "Baja correlación con el mercado accionario",
    "Mínimo histórico: $109.20 (Oct 2024)",
    "Precio de cierre más reciente disponible",
    "Impulsado por rally de metales preciosos",
    "Fuerte desempeño por demanda de activos refugio",
    "Alta liquidez para entrada/salida",
    "Principal exchange para ETFs en EE.UU.",
    "Más de 15 años en el mercado"
  )
)

# Formatear la tabla profesional
ficha_tecnica %>%
  kable(align = "lcl", 
        caption = "Tabla 1. FICHA TÉCNICA DEL ETF GLTR - METALES PRECIOSOS") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE,
                font_size = 12) %>%
  row_spec(0, background = "#1E3A8A", color = "white", bold = TRUE) %>%
  column_spec(1, bold = TRUE, width = "25%") %>%
  column_spec(2, width = "35%") %>%
  column_spec(3, width = "40%", 
              color = "#666666") %>%
  # Resaltar valores importantes
  column_spec(2,
              color = ifelse(
                grepl("\\+[0-9]", ficha_tecnica$Valor), "#27AE60",  # Verde para rendimientos positivos
                ifelse(
                  grepl("^\\$", ficha_tecnica$Valor), "#3498DB",    # Azul para valores monetarios
                  "black"
                )
              ),
              bold = ifelse(
                grepl("\\+[0-9]|^\\$", ficha_tecnica$Valor),
                TRUE,
                FALSE
              ))
Tabla 1. FICHA TÉCNICA DEL ETF GLTR - METALES PRECIOSOS
Característica Valor Nota
Nombre del ETF Aberdeen Standard Physical Precious Metals Basket Shares ETF Nombre completo del instrumento
Símbolo/Ticker GLTR Ticker de negociación principal
Tipo de activo ETF de metales preciosos físicos Clasificación del producto
Activos subyacentes Oro, plata, paladio, platino físicos Metales físicos almacenados en bóvedas
Composición actual Oro: 62%, Plata: 31%, Paladio: 4%, Platino: 3% Distribución basada en valores de mercado actuales
Activos bajo gestión (AUM) $1,850 millones USD Ha crecido 35% en los últimos 12 meses
Expense Ratio 0.60% Competitivo dentro del sector de ETFs de metales
Beta (vs. S&P 500) 0.21 Baja correlación con el mercado accionario
Rango 52 semanas $109.20 - $171.85 Mínimo histórico: $109.20 (Oct 2024)
Precio actual (aprox) $168.50 Precio de cierre más reciente disponible
Rendimiento 2024 +20.3% Impulsado por rally de metales preciosos
Rendimiento YTD 2025 +38.5% (hasta octubre) Fuerte desempeño por demanda de activos refugio
Volumen promedio diario 150,000 acciones Alta liquidez para entrada/salida
Bolsa de cotización NYSE Arca Principal exchange para ETFs en EE.UU.
Fecha de lanzamiento Octubre 2010 Más de 15 años en el mercado

###Distribución de la canasta

# Datos de composición del ETF
composition_data <- data.frame(
  Metal = c("Oro Físico", "Plata Física", "Paladio Físico", "Platino Físico"),
  Porcentaje = c(61.77, 30.72, 4.26, 3.26),
  Valor_Mercado = c("1B", "702M", "97M", "74M")
)

# Añadir etiquetas detalladas
composition_data <- composition_data %>%
  mutate(
    Etiqueta = paste0(
      "<b>", Metal, "</b><br>",
      Porcentaje, "%<br>",
      "(", Valor_Mercado, ")"
    ),
    # Colores metálicos realistas
    Color = c("#FFD700", "#C0C0C0", "#B8B8B8", "#E5E4E2"),
    # Texto para hover
    HoverText = paste0(
      "<b>", Metal, "</b><br>",
      "Composición: <b>", Porcentaje, "%</b><br>",
      "Valor de mercado: <b>", Valor_Mercado, "</b><br>",
      "Aproximado en cartera:<br>",
      case_when(
        Metal == "Oro Físico" ~ "60-65%",
        Metal == "Plata Física" ~ "25-30%",
        Metal == "Paladio Físico" ~ "3-5%",
        Metal == "Platino Físico" ~ "3-5%"
      )
    )
  )

# Crear donut chart interactivo
donut_interactive <- plot_ly(
  composition_data,
  labels = ~Metal,
  values = ~Porcentaje,
  type = 'pie',
  hole = 0.5,  # Esto crea el efecto donut
  textposition = 'outside',
  textinfo = 'label+percent',
  hoverinfo = 'text',
  text = ~HoverText,
  marker = list(
    colors = ~Color,
    line = list(color = '#FFFFFF', width = 2)
  ),
  # Añadir texto en el centro
  domain = list(x = c(0, 1), y = c(0, 1))
) %>%
  layout(
    title = list(
      text = "<b>Composición del ETF GLTR<br>Aberdeen Standard Physical<br>Precious Metals Basket Shares</b>",
      font = list(
        size = 20,
        color = "#1E3A8A",
        family = "Arial, sans-serif"
      ),
      x = 0.5,
      y = 0.95
    ),
    showlegend = TRUE,
    legend = list(
      orientation = "v",
      x = 1.05,
      y = 0.5,
      font = list(size = 12),
      title = list(
        text = "<b>Metales</b>",
        font = list(size = 14)
      )
    ),
    # Añadir anotación en el centro del donut
    annotations = list(
      list(
        text = "<b>Total AUM</b><br>~$1.9B",
        x = 0.5,
        y = 0.5,
        font = list(
          size = 16,
          color = "#1E3A8A",
          family = "Arial, sans-serif"
        ),
        showarrow = FALSE
      )
    ),
    paper_bgcolor = "#F8F9FA",
    plot_bgcolor = "#F8F9FA",
    margin = list(t = 100, b = 80, l = 20, r = 150)
  )

# Mostrar donut chart
donut_interactive

La composición refleja que GLTR está dominado por oro y plata (>92 % en conjunto), mientras que platino y paladio proporcionan exposición industrial complementaria. Esta ponderación es deliberada: oro y plata funcionan como depósitos de valor refugio, mientras que platino y paladio están ligados a demanda industrial. De este modo, GLTR combina protección contra riesgos macroeconómicos con exposición a fundamentales de demanda física de metales preciosos.

##Contexto histórico. El análisis de series de tiempo requiere entender el contexto económico que determina el comportamiento. Como ETF de metales físicos, GLTR refleja ciclos macroeconómicos, decisiones de bancos centrales y eventos geopolíticos. Desde su lanzamiento en 2010, ha experimentado múltiples regímenes: expansiones monetarias post-crisis, normalización, shocks geopolíticos, crisis financieras y el actual rally de máximos históricos.

# Descargar datos
GLTR <- getSymbols("GLTR", src = "yahoo", auto.assign = FALSE, from = "2010-01-01")

# Preparar datos
GLTR_df <- data.frame(
  Fecha = index(GLTR),
  Precio = as.numeric(Cl(GLTR))
)

# Gráfico interactivo
plot_ly(GLTR_df, x = ~Fecha, y = ~Precio, type = "scatter", mode = "lines",
        line = list(color = "#1E3A8A", width = 2),
        hoverinfo = "text",
        text = ~paste("Fecha:", Fecha, "<br>Precio: $", round(Precio, 2))) %>%
  layout(
    title = "<b>ETF GLTR - Serie Histórica (2010-2025)</b>",
    xaxis = list(title = "Fecha", rangeslider = list(visible = TRUE)),
    yaxis = list(title = "Precio (USD)", tickformat = "$,.2f"),
    hovermode = "x unified"
  )

La trayectoria completa de GLTR durante los 15 años de historia desde su creación muestra cinco fases claramente diferenciadas. La ventana de análisis (2022–2025) captura la transición crítica desde volatilidad indeterminada hacia rally sólido, justificando ARIMA para modelar cambios de régimen.

###Rally post-crisis y búsqueda de refugio (2010–2012) GLTR se lanza en octubre de 2010 tras la crisis financiera de 2008–2009, cuando bancos centrales implementan flexibilización cuantitativa (QE) masiva para estabilizar mercados. La Reserva Federal inicia programas de compra de activos sin precedentes (QE1, QE2), el Banco Central Europeo y el Banco de Japón adoptan políticas ultra-expansivas, inyectando miles de millones de dólares en liquidez al sistema financiero.​ En este contexto de expansión monetaria extrema, surge demanda masiva por metales como cobertura contra inflación futura y depreciación de monedas fiduciarias. Durante 2010–2012, GLTR sube de &#95–100 a ~&#115–120, reflejando el rally del oro de &#1.200 a 1.900+ USD/oz y la plata de &#18 a 48+ USD/oz en sus máximos de abril de 2011. La tendencia alcista es coherente con la tesis de refugio: estímulos masivos y temor inflacionario implican apreciación de metales con pocas correcciones

# Plata 2010–2012 (proxy: SLV)
silver_10_12 <- getSymbols("SLV", src = "yahoo", auto.assign = FALSE,
                           from = "2010-01-01", to = "2012-12-31")
silver_10_12_close <- Cl(silver_10_12)

silver_10_12_df <- data.frame(
  fecha  = index(silver_10_12_close),
  precio = as.numeric(silver_10_12_close)
)

g_plata_10_12 <- ggplot(silver_10_12_df, aes(x = fecha, y = precio)) +
  geom_line(color = "gray40", linewidth = 0.8) +
  labs(title = "Precio de la plata 2010–2012 (proxy: SLV)",
       subtitle = "Rally post-crisis y máximos asociados a QE e inflación esperada",
       x = "Fecha", y = "Precio de cierre (USD)") +
  theme_minimal()

g_plata_10_12_int <- ggplotly(g_plata_10_12)
g_plata_10_12_int

La Figura 3 muestra el comportamiento de la plata entre 2010 y 2012 (proxy SLV), con un rally acelerado hasta máximos históricos en 2011 (~$48/oz) y una posterior corrección moderada hacia finales de 2011 e inicios de 2012. Esta dinámica es consistente con el contexto de expansión monetaria extrema y temor inflacionario posterior a la crisis de 2008–2009, en el que los metales preciosos se revalorizaron de forma pronunciada como depósitos de valor refugio. La volatilidad observada en 2011 refleja especulación intensiva y ajustes de portafolio conforme aumentaban preocupaciones sobre sostenibilidad de precios.

###Corrección y consolidación durante normalización monetaria (2013–2015) En 2013, la Reserva Federal anuncia el “tapering” (reducción gradual) de compras de activos y la economía estadounidense muestra recuperación más sólida, aumentando expectativas de subidas futuras en tasas de interés. Con tasas reales esperadas más altas, el costo de oportunidad de mantener oro aumenta. Además, el dólar estadounidense se fortalece, encareciendo commodities para inversionistas internacionales y presionando precios a la baja.​ GLTR cae sostenidamente desde máximos de 2011–2012 a mínimos cercanos a $50–60 hacia mediados de 2015. Este período de corrección es completamente explicable por los fundamentales: normalización monetaria y fortalecimiento del dólar.

###Recuperación moderada bajo incertidumbre política (2016–2019) Entre 2016 y 2019, la trayectoria de GLTR es menos volatil pero aún presenta repuntes puntuales asociados a episodios específicos de incertidumbre. El Brexit en junio de 2016, la elección de Donald Trump en noviembre de 2016, y tensiones comerciales crecientes entre Estados Unidos y China a partir de 2018 generan episodios de aversión al riesgo que benefician temporalmente al oro y otros metales refugio. Sin embargo, estos repuntes son tácticos más que estructurales. Las subidas de tasas realizadas por la Reserva Federal entre 2015 y 2018, junto con la fortaleza del dólar, limitan que GLTR consolide ganancias sostenidas. El precio del ETF oscila entre &#65–&#85 durante este período, formando un patrón de recuperación lenta pero volátil, donde cada crisis geopolítica genera un pico temporal seguido por corrección cuando la tensión se disipa.

###Pandemia COVID-19 y máximos históricos (2020) El año 2020 es un punto de inflexión crítico. En marzo de 2020, la pandemia desencadena un pánico financiero global sin precedentes en la era moderna. Los mercados accionarios caen más de 30 % en semanas. El VIX (índice de volatilidad) alcanza máximos históricos. Los inversionistas huyen masivamente hacia activos considerados seguros. En respuesta, y con una velocidad extraordinaria, los bancos centrales lanzan programas de estímulo sin paralelo histórico: La Reserva Federal reduce tasas a cero y relanza compra de activos (“QE infinito”). El Banco Central Europeo amplía su programa de compra de bonos. Los gobiernos implementan paquetes fiscales masivos de miles de billones de dólares. En este contexto extremo, el oro se comporta de forma excepcional. Alcanza máximos históricos por encima de 2.000 USD/oz hacia agosto de 2020. GLTR refleja este movimiento con un rally espectacular de ~30–40 % anual.

# Descargar datos si no los tienes
GLTR <- getSymbols("GLTR", src = "yahoo", auto.assign = FALSE, from = "2020-01-01", to = "2020-12-31")

# Preparar datos para 2020
datos_2020 <- data.frame(
  Fecha = index(GLTR),
  Precio = as.numeric(Cl(GLTR))
)

# Crear gráfico interactivo
plot_ly(datos_2020, x = ~Fecha) %>%
  add_trace(y = ~Precio, type = 'scatter', mode = 'lines',
            line = list(color = '#1E3A8A', width = 3),
            name = 'Precio GLTR',
            hoverinfo = 'text',
            text = ~paste('<b>Fecha:</b>', Fecha, '<br><b>Precio:</b> $', round(Precio, 2))) %>%
  
  # Eventos clave
  add_trace(x = as.Date('2020-03-16'), y = ~Precio[Fecha == as.Date('2020-03-16')],
            type = 'scatter', mode = 'markers',
            marker = list(color = '#9fa0ff', size = 12, symbol = 'circle'),
            name = 'Colapso mercados',
            hoverinfo = 'text',
            text = '<b>16 Mar 2020:</b> Colapso de mercados globales<br>Fed anuncia estímulos de emergencia') %>%
  
  add_trace(x = as.Date('2020-08-07'), y = ~Precio[Fecha == as.Date('2020-08-07')],
            type = 'scatter', mode = 'markers',
            marker = list(color = '#dab6fc', size = 12, symbol = 'diamond'),
            name = 'Récord oro',
            hoverinfo = 'text',
            text = '<b>07 Ago 2020:</b> Oro supera $2,000/oz<br>Rally histórico de metales preciosos') %>%
  
  layout(
    title = list(
      text = '<b>Comportamiento del ETF GLTR durante la Pandemia COVID-19 (2020)</b>',
      font = list(size = 18, color = '#1E3A8A', family = 'Arial'),
      y = 0.98,  # Posición vertical del título
      x = 0.5,   # Posición horizontal centrada
      xanchor = 'center',
      yanchor = 'top'
    ),
    xaxis = list(
      title = '<b>Fecha</b>',
      type = 'date',
      tickformat = '%b %Y',
      rangeslider = list(visible = TRUE)
    ),
    yaxis = list(
      title = '<b>Precio (USD)</b>',
      tickformat = '$.2f',
      gridcolor = 'lightgray'
    ),
    hovermode = 'x unified',
    plot_bgcolor = 'white',
    paper_bgcolor = '#F8F9FA',
    margin = list(t = 120, b = 80, l = 80, r = 40),  # Aumentado margen superior
    showlegend = TRUE,
    legend = list(
      orientation = 'h',
      x = 0.5,
      xanchor = 'center',
      y = -0.2,
      yanchor = 'top'
    )
  )

La serie muestra un colapso inicial agudo a mediados de marzo (cuando el precio cae a &#65–70) debido al pánico de liquidación indiscriminada. Sin embargo, a partir de finales de marzo/principios de abril, comienza un rally acelerado y sostenido, con GLTR alcanzando nuevos máximos de $#105+ hacia finales de año. Este comportamiento es textualmente consistente con la teoría: metales preciosos actúan como refugio en contextos de riesgo sistémico extremo, pero también se benefician de la expansión monetaria ultra-expansiva que caracteriza la respuesta de los bancos centrales.

###Normalización post-pandemia y corrección (2021) En 2021, a medida que avanzan las campañas de vacunación y la actividad económica se recupera, el panorama vuelve a cambiar. Los inversionistas comienzan a rotar capital desde activos defensivos hacia activos cíclicos. Las expectativas de inflación permanecen elevadas, pero ya están incorporadas en los precios. Los bancos centrales comienzan a discutir públicamente la reducción de estímulos (“taper talk”). El resultado es una corrección en GLTR de aproximadamente –10 % en el año. El oro retrocede desde máximos de &#2.000+ a niveles cercanos a &#1.700–1.800. GLTR refleja esta dinámica con una serie principalmente lateral con tendencia bajista moderada. Este comportamiento no es sorpresa: representa la normalización esperada tras un pico extremo de aversión al riesgo.

###Guerra Rusia-Ucrania, inflación histórica y volatilidad sin precedentes (2022) El 24 de febrero de 2022, Rusia invade Ucrania, desencadenando la mayor crisis geopolítica en Europa en 30 años. El shock de oferta en energía (petróleo sube de &#80 a &#120+ por barril, gas natural europeo se multiplica por 5) y alimentos (trigo, maíz, aceites vegetales) dispara inflación global a máximos de 40+ años: inflación estadounidense alcanza 9.1% en junio de 2022, inflación europea supera 10%.​ Simultáneamente, la Reserva Federal realiza subidas de tasas históricas bajo Jerome Powell: de prácticamente 0% en marzo de 2022 a más de 4% hacia finales de año, velocidad más rápida desde los años 1980s bajo Paul Volcker. El Banco Central Europeo, Banco de Inglaterra y otros bancos centrales siguen decisiones de endurecimiento similares, marcando el fin definitivo de la era de dinero barato iniciada en 2008.​ GLTR experimenta choque de fuerzas contradictorias: riesgo geopolítico extremo e inflación acelerada favorecen oro como cobertura, pero tasas de interés reales muy altas (superiores a 2% en términos reales hacia finales de 2022) encarecen dramáticamente su costo de oportunidad. El resultado es volatilidad extrema con GLTR oscilando entre $70–95, cerrando prácticamente plano (~0% anual) sin dirección clara.

# Oro 2022 (proxy: GLD)
gold_2022 <- getSymbols("GLD", src = "yahoo", auto.assign = FALSE,
                        from = "2022-01-01", to = "2022-12-31")
gold_2022_close <- Cl(gold_2022)

gold_2022_df <- data.frame(
  fecha  = index(gold_2022_close),
  precio = as.numeric(gold_2022_close)
)

g_oro_2022 <- ggplot(gold_2022_df, aes(x = fecha, y = precio)) +
  geom_line(color = "goldenrod", linewidth = 0.8) +
  labs(title = "Precio del oro en 2022 (proxy: GLD)",
       subtitle = "Volatilidad por guerra en Ucrania e incremento de tasas",
       x = "Fecha", y = "Precio de cierre (USD)") +
  theme_minimal()

g_oro_2022_int <- ggplotly(g_oro_2022)
g_oro_2022_int

La Figura 5 presenta la evolución del precio del oro durante 2022 (proxy GLD), donde se observa un repunte brusco tras la invasión de Ucrania en febrero-marzo, alcanzando niveles cercanos a &#190 por acción de GLD (equivalente a ~&#1.950/oz de oro spot), seguido de una corrección sostenida a medida que se intensifica el ciclo de subidas de tasas durante el segundo semestre. Este patrón respalda la idea de un año dominado por fuerzas contrapuestas: el oro reacciona inicialmente como activo refugio ante el choque geopolítico, pero pierde tracción cuando el endurecimiento monetario eleva de forma significativa las tasas reales, haciendo atractivos activos remunerados (bonos, depósitos) frente a oro que no genera rendimiento.

###Crisis bancaria regional y reactivación de demanda refugio (marzo 2023) En marzo de 2023, la quiebra de Silicon Valley Bank (SVB) y otros bancos regionales (Signature Bank, First Republic) desencadena pánico bancario por riesgo de liquidez, no por insolvencia sistémica como en 2008. Los inversionistas reaccionan inmediatamente con demanda masiva por oro como refugio, que dispara por encima de 2.000 USD/oz en días. GLTR experimenta pico abrupto de 5–8%.​ Sin embargo, este es un evento táctico, no estructural. Respuesta rápida de autoridades (garantías de depósitos, líneas de crédito de emergencia) alivia tensiones y GLTR retrocede gradualmente, cerrando 2023 con rentabilidad ligeramente positiva de +2%. El patrón es típico de shocks puntuales que generan picos temporales pero no tendencias sostenidas.

# Descargar datos para 2023 y 2024
GLTR_2023 <- getSymbols("GLTR", src = "yahoo", auto.assign = FALSE, from = "2023-01-01", to = "2023-12-31")
GLTR_2024 <- getSymbols("GLTR", src = "yahoo", auto.assign = FALSE, from = "2024-01-01", to = "2024-12-31")

# Preparar datos para 2023
datos_2023 <- data.frame(
  Fecha = index(GLTR_2023),
  Precio = as.numeric(Cl(GLTR_2023))
) %>%
  mutate(
    Dia = seq_along(Fecha),
    Año = "2023",
    Precio_Norm = Precio / first(Precio) * 100
  )

# Preparar datos para 2024
datos_2024 <- data.frame(
  Fecha = index(GLTR_2024),
  Precio = as.numeric(Cl(GLTR_2024))
) %>%
  mutate(
    Dia = seq_along(Fecha),
    Año = "2024",
    Precio_Norm = Precio / first(Precio) * 100
  )

# Combinar datos
datos_comparativos <- bind_rows(datos_2023, datos_2024)

# Crear gráfico comparativo interactivo
plot_ly(datos_comparativos, x = ~Dia) %>%
  # Línea para 2023
  add_trace(data = subset(datos_comparativos, Año == "2023"),
            y = ~Precio_Norm,
            type = 'scatter',
            mode = 'lines',
            line = list(color = '#e0c3fc', width = 3),
            name = '2023',
            hoverinfo = 'text',
            text = ~paste('<b>2023 - Día', Dia, '</b><br>',
                          'Fecha:', Fecha, '<br>',
                          'Precio: $', round(Precio, 2), '<br>',
                          'Normalizado:', round(Precio_Norm, 1))) %>%
  
  # Línea para 2024
  add_trace(data = subset(datos_comparativos, Año == "2024"),
            y = ~Precio_Norm,
            type = 'scatter',
            mode = 'lines',
            line = list(color = '#957fef', width = 3),
            name = '2024',
            hoverinfo = 'text',
            text = ~paste('<b>2024 - Día', Dia, '</b><br>',
                          'Fecha:', Fecha, '<br>',
                          'Precio: $', round(Precio, 2), '<br>',
                          'Normalizado:', round(Precio_Norm, 1))) %>%
  
  # Línea de referencia en 100
  add_trace(x = c(0, max(datos_comparativos$Dia)),
            y = c(100, 100),
            type = 'scatter',
            mode = 'lines',
            line = list(color = 'gray', width = 1, dash = 'dash'),
            name = 'Línea base (100)',
            showlegend = FALSE) %>%
  
  # Layout
  layout(
    title = list(
      text = '<b>Comparativo de Desempeño: ETF GLTR 2023 vs 2024</b>',
      font = list(size = 22, color = '#1E3A8A')
    ),
    xaxis = list(
      title = '<b>Días de negociación en el año</b>',
      gridcolor = 'lightgray'
    ),
    yaxis = list(
      title = '<b>Precio Normalizado (Inicio = 100)</b>',
      gridcolor = 'lightgray'
    ),
    hovermode = 'x unified',
    plot_bgcolor = 'white',
    paper_bgcolor = '#F8F9FA',
    legend = list(
      orientation = 'h',
      x = 0.5,
      y = -0.15,
      xanchor = 'center'
    ),
    margin = list(t = 80, b = 100, l = 80, r = 40)
  )

La Figura 4 contrasta ambos períodos: la crisis bancaria (febrero–mayo 2023) muestra trayectoria errática con cambios frecuentes, mientras el rally 2024 (junio–octubre) exhibe pendiente alcista prácticamente lineal sin correcciones, evidenciando la diferencia entre evento táctico y fundamentales sólidos sostenidos

###Rally estructural y máximos históricos (2024–2025) A partir de enero de 2024, confluyen cuatro factores estructurales que generan rally robusto: la deuda pública en máximos históricos favorece oro como cobertura inflacionaria, los bancos centrales señalizan futuras reducciones de tasas reduciendo costo de oportunidad del oro, la guerra Ucrania y tensiones comerciales EE.UU.-China sustentan demanda de refugio, y las sanciones a Rusia presionan suministro de paladio.​ El resultado es una apreciación pronunciada: GLTR sube de $100 a $140 en diez meses (ganancia de +40%), oro alcanza máximos de 2.500+ USD/oz, y plata alcanza máximos no vistos en década aproximadamente $30–32/oz. La aceleración es concluyente en términos anuales: 2023 cierra plano con +2.1%, 2024 muestra rally de +21.2%, y 2025 hasta octubre registra +68.7%, confirmando intensificación de factores fundamentales.

Figura 5. Desempeño comparativo por año (2023–2025)

# Descargar datos desde 2023
GLTR_all <- getSymbols("GLTR", src = "yahoo", auto.assign = FALSE, from = "2023-01-01")

# Función para preparar datos por año
preparar_datos_año <- function(año, datos) {
  # Filtrar por año
  datos_año <- datos[year(index(datos)) == año]
  
  if (nrow(datos_año) == 0) return(NULL)
  
  # Crear dataframe
  df <- data.frame(
    Fecha = index(datos_año),
    Precio = as.numeric(Cl(datos_año))
  )
  
  # Calcular día del año y precio normalizado
  df <- df %>%
    mutate(
      Dia_del_año = row_number(),
      Año = as.character(año),
      Precio_Norm = Precio / first(Precio) * 100,
      Retorno = (Precio / first(Precio) - 1) * 100
    )
  
  return(df)
}

# Preparar datos para cada año
datos_2023 <- preparar_datos_año(2023, GLTR_all)
datos_2024 <- preparar_datos_año(2024, GLTR_all)
datos_2025 <- preparar_datos_año(2025, GLTR_all)

# Combinar todos los datos
datos_todos <- bind_rows(datos_2023, datos_2024, datos_2025)

# Crear gráfico interactivo
plot_ly(datos_todos, x = ~Dia_del_año) %>%
  
  # Año 2023
  add_trace(data = subset(datos_todos, Año == "2023"),
            y = ~Precio_Norm,
            type = 'scatter',
            mode = 'lines+markers',
            line = list(color = '#b79ced', width = 2.5),
            marker = list(size = 6, color = '#dec0f1'),
            name = '2023',
            hoverinfo = 'text',
            text = ~paste('<b>2023 - Día', Dia_del_año, '</b><br>',
                          'Fecha:', format(Fecha, '%d/%m/%Y'), '<br>',
                          'Precio real: $', round(Precio, 2), '<br>',
                          'Normalizado:', round(Precio_Norm, 1), '<br>',
                          'Retorno:', round(Retorno, 1), '%')) %>%
  
  # Año 2024
  add_trace(data = subset(datos_todos, Año == "2024"),
            y = ~Precio_Norm,
            type = 'scatter',
            mode = 'lines+markers',
            line = list(color = '#8e94f2', width = 2.5),
            marker = list(size = 6, color = '#8e94f2'),
            name = '2024',
            hoverinfo = 'text',
            text = ~paste('<b>2024 - Día', Dia_del_año, '</b><br>',
                          'Fecha:', format(Fecha, '%d/%m/%Y'), '<br>',
                          'Precio real: $', round(Precio, 2), '<br>',
                          'Normalizado:', round(Precio_Norm, 1), '<br>',
                          'Retorno:', round(Retorno, 1), '%')) %>%
  
  # Año 2025 (hasta la fecha disponible)
  add_trace(data = subset(datos_todos, Año == "2025"),
            y = ~Precio_Norm,
            type = 'scatter',
            mode = 'lines+markers',
            line = list(color = '#1E3A8A', width = 2.5),
            marker = list(size = 6, color = '#1E3A8A'),
            name = '2025 (hasta fecha)',
            hoverinfo = 'text',
            text = ~paste('<b>2025 - Día', Dia_del_año, '</b><br>',
                          'Fecha:', format(Fecha, '%d/%m/%Y'), '<br>',
                          'Precio real: $', round(Precio, 2), '<br>',
                          'Normalizado:', round(Precio_Norm, 1), '<br>',
                          'Retorno:', round(Retorno, 1), '%')) %>%
  
  # Línea de referencia en 100
  add_trace(x = c(0, max(datos_todos$Dia_del_año, na.rm = TRUE)),
            y = c(100, 100),
            type = 'scatter',
            mode = 'lines',
            line = list(color = 'gray', width = 1, dash = 'dash'),
            name = 'Línea base (100)',
            showlegend = FALSE,
            hoverinfo = 'skip') %>%
  
  # Layout
  layout(
    title = list(
      text = '<b>Comparativo de Desempeño Anual - ETF GLTR</b><br><span style="font-size:14px">Cada año normalizado a 100 en su primer día de negociación</span>',
      font = list(size = 22, color = '#1E3A8A')
    ),
    xaxis = list(
      title = '<b>Día del año de negociación</b>',
      gridcolor = 'lightgray'
    ),
    yaxis = list(
      title = '<b>Índice Normalizado (Inicio = 100)</b>',
      gridcolor = 'lightgray'
    ),
    hovermode = 'x unified',
    plot_bgcolor = 'white',
    paper_bgcolor = '#F8F9FA',
    legend = list(
      orientation = 'h',
      x = 0.5,
      y = -0.15,
      xanchor = 'center',
      bgcolor = 'rgba(255,255,255,0.8)'
    ),
    margin = list(t = 100, b = 100, l = 80, r = 40),
    
    # Anotaciones con rendimiento final de cada año
    annotations = list(
      list(
        x = max(datos_2023$Dia_del_año, na.rm = TRUE),
        y = tail(datos_2023$Precio_Norm, 1),
        text = paste('2023:', round(tail(datos_2023$Retorno, 1), 1), '%'),
        showarrow = FALSE,
        font = list(size = 12, color = '#b7bced'),
        xanchor = 'left',
        xshift = 10
      ),
      list(
        x = max(datos_2024$Dia_del_año, na.rm = TRUE),
        y = tail(datos_2024$Precio_Norm, 1),
        text = paste('2024:', round(tail(datos_2024$Retorno, 1), 1), '%'),
        showarrow = FALSE,
        font = list(size = 12, color = '#8e94f2'),
        xanchor = 'left',
        xshift = 10
      ),
      list(
        x = max(datos_2025$Dia_del_año, na.rm = TRUE),
        y = tail(datos_2025$Precio_Norm, 1),
        text = paste('2025:', round(tail(datos_2025$Retorno, 1), 1), '%'),
        showarrow = FALSE,
        font = list(size = 12, color = '#1E3A8A'),
        xanchor = 'left',
        xshift = 10
      )
    )
  )

La serie captura transición crítica desde crisis táctica en 2023 hasta rally estructural en 2024–2025, evidenciando no estacionariedad que justifica ARIMA para capturar cambios de régimen y realizar pronósticos condicionales al entorno macroeconómico actual.

###Síntesis: Estructura de la serie y factores determinantes.

La trayectoria de 15 años (2010–2025) se sintetiza de la siguiente manera:

# Crear tabla de síntesis histórica
sintesis_historica <- data.frame(
  Período = c(
    "2010–2012",
    "2013–2015", 
    "2016–2019",
    "2020",
    "2021",
    "2022",
    "2023",
    "2024–2025"
  ),
  Comportamiento = c(
    "Rally alcista",
    "Corrección",
    "Laterización volátil",
    "Rally extremo",
    "Corrección",
    "Volatilidad extrema",
    "Recuperación táctica",
    "Rally estructural"
  ),
  Factores_clave = c(
    "Estímulos post-2008, temor inflación, búsqueda refugio",
    "Tapering Fed, fortaleza dólar, normalización monetaria",
    "Incertidumbre política (Brexit, Trump, guerra comercial), tasas moderadas",
    "Pandemia COVID, pánico financiero, QE infinito, máximos oro",
    "Recuperación económica, rotación a cíclicos, normalización de tasas",
    "Invasión Ucrania (alcista) vs. endurecimiento Fed (bajista) → plano",
    "Crisis bancaria puntual, demanda refugio momentánea, luego normalización",
    "Deuda pública ↑, tasas reales esperadas ↓, incertidumbre geopolítica, máximos históricos"
  )
)

# Crear tabla profesional
sintesis_historica %>%
  kable(
    align = "lll",
    col.names = c("PERÍODO", "COMPORTAMIENTO", "FACTORES CLAVE"),
    caption = "<center><h3 style='color: #1E3A8A;'>Tabla 2. SÍNTESIS HISTÓRICA - TRAYECTORIA DEL ETF GLTR (2010-2025)</h3></center>",
    escape = FALSE
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = FALSE,
    position = "center",
    font_size = 13,
    fixed_thead = TRUE
  ) %>%
  row_spec(
    0,
    background = "#957fef",
    color = "white",
    bold = TRUE,
    align = "center",
    extra_css = "border-bottom: 2px solid #FFFFFF;"
  ) %>%
  column_spec(
    1,
    bold = TRUE,
    width = "15%",
    background = "#F8FAFC",
    extra_css = "border-right: 1px solid #E5E7EB;"
  ) %>%
  column_spec(
    2,
    width = "20%",
    background = "#FFFFFF",
    extra_css = "border-right: 1px solid #E5E7EB;"
  ) %>%
  column_spec(
    3,
    width = "65%",
    background = "#FFFFFF"
  ) %>%
  # Añadir notas al pie
  footnote(
    general = "Fuente: Análisis histórico basado en datos de Yahoo Finance, Bloomberg y Aberdeen Standard Investments",
    general_title = "Nota:",
    footnote_as_chunk = TRUE,
    title_format = c("italic", "bold")
  )

Tabla 2. SÍNTESIS HISTÓRICA - TRAYECTORIA DEL ETF GLTR (2010-2025)

PERÍODO COMPORTAMIENTO FACTORES CLAVE
2010–2012 Rally alcista Estímulos post-2008, temor inflación, búsqueda refugio
2013–2015 Corrección Tapering Fed, fortaleza dólar, normalización monetaria
2016–2019 Laterización volátil Incertidumbre política (Brexit, Trump, guerra comercial), tasas moderadas
2020 Rally extremo Pandemia COVID, pánico financiero, QE infinito, máximos oro
2021 Corrección Recuperación económica, rotación a cíclicos, normalización de tasas
2022 Volatilidad extrema Invasión Ucrania (alcista) vs. endurecimiento Fed (bajista) → plano
2023 Recuperación táctica Crisis bancaria puntual, demanda refugio momentánea, luego normalización
2024–2025 Rally estructural Deuda pública ↑, tasas reales esperadas ↓, incertidumbre geopolítica, máximos históricos
Nota: Fuente: Análisis histórico basado en datos de Yahoo Finance, Bloomberg y Aberdeen Standard Investments

GLTR no es estacionaria porque está impulsada por ciclos macroeconómicos, decisiones de bancos centrales y cambios en percepción de riesgo global—todos no estacionarios. La ventana 2022–2025 captura transición clara desde volatilidad extrema (2022) a rally sólido (2024–2025), validando aplicabilidad de ARIMA para capturar cambios de régimen y realizar pronósticos condicionales.​

##Estadisticas descriptivas

###Estadisticas descriptivas de la serie La Tabla 2 presenta un resumen numérico de los estadísticos descriptivos fundamentales del ETF GLTR durante el período de análisis comprendido entre octubre de 2022 y octubre de 2025.

# Calcular estadísticas básicas
estadisticas_basicas <- GLTR_df %>%
  filter(Fecha >= "2022-10-31" & Fecha <= "2025-10-31") %>%
  summarise(
    Media = mean(Precio),
    Mediana = median(Precio),
    Desviacion = sd(Precio),
    Minimo = min(Precio),
    Maximo = max(Precio),
    Q1 = quantile(Precio, 0.25),
    Q3 = quantile(Precio, 0.75)
  ) %>%
  mutate(across(where(is.numeric), ~round(., 2)))

# Crear el data frame directamente
estadisticas_df <- data.frame(
  Estadistica = c("Media", "Mediana", "Desviación Estándar", 
                  "Mínimo", "Máximo", "Primer Cuartil (Q1)", 
                  "Tercer Cuartil (Q3)"),
  Valor = c(
    estadisticas_basicas$Media,
    estadisticas_basicas$Mediana,
    estadisticas_basicas$Desviacion,
    estadisticas_basicas$Minimo,
    estadisticas_basicas$Maximo,
    estadisticas_basicas$Q1,
    estadisticas_basicas$Q3
  )
)

# Crear tabla con GT - versión simplificada
tabla_estadisticas <- estadisticas_df %>%
  gt() %>%
  tab_header(
    title = "Tabla 1. Estadísticas Descriptivas del ETF GLTR",
    subtitle = "Período: Octubre 2022 - Octubre 2025"
  ) %>%
  fmt_currency(
    columns = Valor,
    currency = "USD",
    decimals = 2
  ) %>%
  cols_label(
    Estadistica = "Estadística",
    Valor = "Valor (USD)"
  ) %>%
  # Estilo para encabezado de columnas
  tab_style(
    style = list(
      cell_fill(color = "#957fef"),
      cell_text(color = "white", weight = "bold")
    ),
    locations = cells_column_labels()
  ) %>%
  # Estilo para filas alternas
  tab_style(
    style = cell_fill(color = "#f8f9fa"),
    locations = cells_body(rows = seq(1, nrow(estadisticas_df), 2))
  ) %>%
  # Bordes
  tab_style(
    style = cell_borders(
      sides = c("top", "bottom"),
      color = "#dee2e6",
      weight = px(1)
    ),
    locations = cells_body()
  ) %>%
  # Fuente de nota
  tab_source_note(
    source_note = "Fuente: Datos históricos del ETF GLTR"
  ) %>%
  # Opciones básicas de tabla
  tab_options(
    table.font.names = "Arial",
    heading.title.font.size = px(16),
    heading.subtitle.font.size = px(14),
    table_body.hlines.color = "transparent",
    source_notes.font.size = px(12)
  )

# Mostrar la tabla
tabla_estadisticas

El precio promedio fue de &#107.28 USD con una mediana de &#101.79 USD. La diferencia de &#5.49 entre ambas medidas sugiere una distribución ligeramente asimétrica hacia valores superiores, característica típica de series financieras donde eventos de apreciación significativa generan colas derechas prolongadas. La desviación estándar de &#22.90 USD (21.3% de la media) evidencia una variabilidad considerable, típica en mercados de metales preciosos sujetos a ciclos económicos y expectativas inflacionarias. El análisis de cuartiles revela una perspectiva más matizada: con Q1 en &#88.58 USD y Q3 en &#119.92 USD, el rango intercuartílico de &#31.34 USD indica que el 50% central de las observaciones fue relativamente estrecho comparado con la amplitud total de &#109.79 USD. Los valores extremos fueron ocasionales, no representativos del comportamiento típico de la serie.

###Distribución de Precios por Año: Análisis del Boxplot Interactivo

La visualización mediante boxplots interactivos muestra el comportamiento de la serie temporal por año calendario, exponiendo la evolución de la tendencia central, dispersión y valores extremos a lo largo del período de entrenamiento. Este análisis comparativo revela heterogeneidades temporales en la variabilidad de precios, distinguiendo años de estabilidad relativa frente a períodos de volatilidad extrema—información esencial para comprender los cambios estructurales de la serie y anticipar la especificación del modelo de pronóstico.

# Asegurarnos de que la columna Fecha es de tipo Date
GLTR_df <- GLTR_df %>%
  mutate(Fecha = as.Date(Fecha))

# Extraer el año para el análisis
GLTR_df <- GLTR_df %>%
  mutate(Año = as.factor(format(Fecha, "%Y"))) %>%
  filter(Año %in% c("2022", "2023", "2024", "2025"))

# Crear dataframes separados para cada año
df_2022 <- GLTR_df %>% filter(Año == "2022")
df_2023 <- GLTR_df %>% filter(Año == "2023")
df_2024 <- GLTR_df %>% filter(Año == "2024")
df_2025 <- GLTR_df %>% filter(Año == "2025")

# Definir colores elegantes para cada año
colors <- c(
  "2022" = "#efd9ce",   
  "2023" = "#dec0f1",    
  "2024" = "#b79ced",    
  "2025" = "#957fef",    
  "Todos" = "#6C757D"    # Gris para "Todos"
)

# Crear el gráfico base con todos los años
fig <- plot_ly() %>%
  # Trazo para 2022
  add_boxplot(
    data = df_2022,
    y = ~Precio,
    name = "2022",
    marker = list(
      color = colors["2022"],
      size = 5,
      line = list(color = 'white', width = 1)
    ),
    line = list(color = colors["2022"], width = 2),
    fillcolor = 'rgba(46, 134, 171, 0.5)',
    boxmean = TRUE,
    visible = TRUE
  ) %>%
  # Trazo para 2023
  add_boxplot(
    data = df_2023,
    y = ~Precio,
    name = "2023",
    marker = list(
      color = colors["2023"],
      size = 5,
      line = list(color = 'white', width = 1)
    ),
    line = list(color = colors["2023"], width = 2),
    fillcolor = 'rgba(162, 59, 114, 0.5)',
    boxmean = TRUE,
    visible = TRUE
  ) %>%
  # Trazo para 2024
  add_boxplot(
    data = df_2024,
    y = ~Precio,
    name = "2024",
    marker = list(
      color = colors["2024"],
      size = 5,
      line = list(color = 'white', width = 1)
    ),
    line = list(color = colors["2024"], width = 2),
    fillcolor = 'rgba(241, 143, 1, 0.5)',
    boxmean = TRUE,
    visible = TRUE
  ) %>%
  # Trazo para 2025
  add_boxplot(
    data = df_2025,
    y = ~Precio,
    name = "2025",
    marker = list(
      color = colors["2025"],
      size = 5,
      line = list(color = 'white', width = 1)
    ),
    line = list(color = colors["2025"], width = 2),
    fillcolor = 'rgba(115, 171, 132, 0.5)',
    boxmean = TRUE,
    visible = TRUE
  ) %>%
  # Diseño del gráfico
  layout(
    title = list(
      text = "<b>Boxplot Interactivo: Distribución de Precios del ETF GLTR</b>",
      font = list(
        family = "Arial, sans-serif",
        size = 22,
        color = "#2c3e50"
      ),
      x = 0.5,
      xanchor = "center",
      y = 0.95
    ),
    xaxis = list(
      title = "<b>Año</b>",
      titlefont = list(
        family = "Arial, sans-serif",
        size = 16,
        color = "#2c3e50"
      ),
      tickfont = list(
        family = "Arial, sans-serif",
        size = 14,
        color = "#2c3e50"
      ),
      showgrid = TRUE,
      gridcolor = "rgba(200, 200, 200, 0.2)",
      gridwidth = 0.5,
      showline = TRUE,
      linecolor = "#bdc3c7",
      linewidth = 1.5
    ),
    yaxis = list(
      title = "<b>Precio (USD)</b>",
      titlefont = list(
        family = "Arial, sans-serif",
        size = 16,
        color = "#2c3e50"
      ),
      tickfont = list(
        family = "Arial, sans-serif",
        size = 13,
        color = "#2c3e50"
      ),
      tickformat = "$.2f",
      showgrid = TRUE,
      gridcolor = "rgba(200, 200, 200, 0.2)",
      gridwidth = 0.5,
      zeroline = TRUE,
      zerolinecolor = "#bdc3c7",
      zerolinewidth = 1
    ),
    plot_bgcolor = "rgba(255, 255, 255, 0.95)",
    paper_bgcolor = "rgba(248, 249, 250, 1)",
    margin = list(l = 80, r = 40, t = 100, b = 80),
    showlegend = TRUE,
    legend = list(
      orientation = "h",
      x = 0.5,
      xanchor = "center",
      y = -0.15,
      font = list(
        family = "Arial, sans-serif",
        size = 13
      )
    ),
    hovermode = "x unified",
    # Definir los botones de actualización
    updatemenus = list(
      list(
        type = "buttons",
        direction = "right",
        x = 0.5,
        xanchor = "center",
        y = 1.15,
        yanchor = "top",
        showactive = TRUE,
        bgcolor = "rgba(255, 255, 255, 0.8)",
        bordercolor = "#dee2e6",
        borderwidth = 1,
        buttons = list(
          # Botón para mostrar TODOS los años
          list(
            method = "update",
            args = list(
              list(visible = c(TRUE, TRUE, TRUE, TRUE)),
              list(title = "<b>Boxplot Interactivo: Distribución de Precios del ETF GLTR (Todos los Años)</b>",
                   xaxis = list(title = "<b>Año</b>"))
            ),
            label = "Todos los Años"
          ),
          # Botón para mostrar solo 2022
          list(
            method = "update",
            args = list(
              list(visible = c(TRUE, FALSE, FALSE, FALSE)),
              list(title = "<b>Boxplot Interactivo: Distribución de Precios del ETF GLTR (2022)</b>",
                   xaxis = list(title = "<b>2022</b>"))
            ),
            label = "2022"
          ),
          # Botón para mostrar solo 2023
          list(
            method = "update",
            args = list(
              list(visible = c(FALSE, TRUE, FALSE, FALSE)),
              list(title = "<b>Boxplot Interactivo: Distribución de Precios del ETF GLTR (2023)</b>",
                   xaxis = list(title = "<b>2023</b>"))
            ),
            label = "2023"
          ),
          # Botón para mostrar solo 2024
          list(
            method = "update",
            args = list(
              list(visible = c(FALSE, FALSE, TRUE, FALSE)),
              list(title = "<b>Boxplot Interactivo: Distribución de Precios del ETF GLTR (2024)</b>",
                   xaxis = list(title = "<b>2024</b>"))
            ),
            label = "2024"
          ),
          # Botón para mostrar solo 2025
          list(
            method = "update",
            args = list(
              list(visible = c(FALSE, FALSE, FALSE, TRUE)),
              list(title = "<b>Boxplot Interactivo: Distribución de Precios del ETF GLTR (2025)</b>",
                   xaxis = list(title = "<b>2025</b>"))
            ),
            label = "2025"
          )
        )
      )
    )
  ) %>%
  # Añadir información de hover personalizada
  layout(
    hoverlabel = list(
      bgcolor = "white",
      bordercolor = "#dee2e6",
      font = list(
        family = "Arial, sans-serif",
        size = 13,
        color = "#2c3e50"
      )
    )
  ) %>%
  # Añadir anotación explicativa
  add_annotations(
    text = "<i>Haz clic en los botones para ver la distribución de precios por año</i>",
    x = 0.5,
    y = -0.2,
    xref = "paper",
    yref = "paper",
    xanchor = "center",
    showarrow = FALSE,
    font = list(
      family = "Arial, sans-serif",
      size = 12,
      color = "#6c757d"
    )
  )

# Mostrar el gráfico interactivo
fig

El año 2022 se caracteriza por una distribución estrecha y homogénea, con una mediana de &#86.62 USD y un rango intercuartílico de apenas &#1.73 USD. La caja del boxplot es prácticamente invisible, indicando que el 50% central de las observaciones estuvo concentrado en un intervalo minúsculo. El rango total fue de &#10.59 USD, representando una variabilidad relativa del 13.4% respecto a la mediana. La media (&#85.88) y la mediana (&#86.62) están prácticamente alineadas, sugiriendo una distribución simétrica con ausencia de picos significativos.

Durante 2023 se observa un incremento moderado pero notable en los niveles de precio, con una mediana de &#88.86 USD, representando un aumento del 2.6% respecto a 2022. El rango intercuartílico aumentó a &#4.10 USD, triplicándose respecto al año anterior, lo que indica una expansión de la variabilidad dentro del rango central. El rango total se amplió a &#14.09 USD, con máximos alcanzando &#95.57. La media (&#88.85) nuevamente coincide prácticamente con la mediana ($88.86), manteniendo la simetría distribucional. Este año marca una transición: los precios comenzaron a recuperarse gradualmente de los mínimos de 2022, pero la volatilidad aún se mantuvo contenida.

El año 2024 presenta un salto significativo en los niveles de precio, con una mediana de &#104.56 USD, equivalente a un incremento del 17.7% respecto a 2023. El rango intercuartílico creció sustancialmente a &#12.78 USD, representando casi el triple del observado en 2023. La caja del boxplot se expande visiblemente, reflejando una mayor dispersión en las observaciones centrales. El rango total fue de &#36.22 USD, con una variabilidad relativa del 34.7% respecto a la mediana. La media (&#103.62) nuevamente se alinea con la mediana (&#104.56), manteniendo simetría. El año 2025 (período parcial de enero a octubre) muestra la mayor apreciación y volatilidad de todo el período, con una mediana de &#138.65 USD, generando un aumento del 32.6% respecto a 2024. El rango intercuartílico alcanzó &#27.41 USD, la mayor dispersión registrada en los cuatro años y aproximadamente 6.7 veces mayor que la de 2022. La caja es considerablemente más amplia, reflejando una heterogeneidad considerable en la distribución central. El rango total fue de &#77.48 USD, con una variabilidad relativa del 55.9% respecto a la mediana, la más elevada del período. La media (&#141.72) se mantiene ligeramente superior a la mediana ($138.65), sugiriendo eventos de precios particularmente elevados que mueven el promedio. La progresión del 2022 al 2025 revela un patrón de volatilidad creciente acompañado de apreciación sistemática. Mientras que en 2022 la distribución fue cristalina y homogénea (IQR = &#1.73), en 2025 la dispersión se multiplicó por más de 15 veces (IQR = &#27.41).

###Gráfico de tendencias

La visualización de la serie temporal superpuesta con su componente de tendencia separa el comportamiento del precio en dos dimensiones: los precios diarios y la dirección subyacente de largo plazo.

# Convertir a serie temporal para descomposición
serie_ts <- ts(GLTR_df$Precio, 
               start = c(2022, 10), 
               frequency = 365)

# Descomposición STL (Seasonal and Trend decomposition using Loess)
descomposicion <- stl(serie_ts, s.window = "periodic")

# Crear dataframe para plotly
descomp_df <- data.frame(
  Fecha = GLTR_df$Fecha,
  Original = GLTR_df$Precio,
  Tendencia = as.numeric(descomposicion$time.series[, "trend"])
)

# Gráfico interactivo de solo Original + Tendencia
fig_original_tendencia <- plot_ly(descomp_df) %>%
  # Serie original
  add_trace(x = ~Fecha, y = ~Original, type = 'scatter', mode = 'lines',
            name = 'Serie Original', 
            line = list(color = 'rgba(46, 134, 171, 0.4)', width = 1),
            hovertemplate = '<b>Original</b>: $%{y:.2f}<br>%{x|%d-%b-%Y}<extra></extra>') %>%
  # Tendencia
  add_trace(x = ~Fecha, y = ~Tendencia, type = 'scatter', mode = 'lines',
            name = 'Tendencia', 
            line = list(color = '#7161ef', width = 3),
            hovertemplate = '<b>Tendencia</b>: $%{y:.2f}<br>%{x|%d-%b-%Y}<extra></extra>') %>%
  # Diseño del gráfico
  layout(
    title = list(
      text = "<b>Serie Temporal Original y Tendencia del ETF GLTR</b>",
      font = list(
        family = "Arial, sans-serif",
        size = 22,
        color = "#2c3e50"
      ),
      x = 0.5,
      xanchor = "center",
      y = 0.95
    ),
    xaxis = list(
      title = "<b>Fecha</b>",
      titlefont = list(
        family = "Arial, sans-serif",
        size = 16,
        color = "#2c3e50"
      ),
      tickfont = list(
        family = "Arial, sans-serif",
        size = 12,
        color = "#2c3e50"
      ),
      showgrid = TRUE,
      gridcolor = "rgba(200, 200, 200, 0.2)",
      gridwidth = 0.5,
      showline = TRUE,
      linecolor = "#bdc3c7",
      linewidth = 1.5,
      rangeslider = list(visible = FALSE)  # Range slider desactivado
    ),
    yaxis = list(
      title = "<b>Precio (USD)</b>",
      titlefont = list(
        family = "Arial, sans-serif",
        size = 16,
        color = "#2c3e50"
      ),
      tickfont = list(
        family = "Arial, sans-serif",
        size = 13,
        color = "#2c3e50"
      ),
      tickformat = "$.2f",
      showgrid = TRUE,
      gridcolor = "rgba(200, 200, 200, 0.2)",
      gridwidth = 0.5,
      zeroline = TRUE,
      zerolinecolor = "#bdc3c7",
      zerolinewidth = 1
    ),
    plot_bgcolor = "rgba(255, 255, 255, 0.95)",
    paper_bgcolor = "rgba(248, 249, 250, 1)",
    margin = list(l = 80, r = 40, t = 100, b = 80),
    hovermode = "x unified",
    # Botones de actualización
    updatemenus = list(
      list(
        type = "buttons",
        direction = "right",
        x = 0.5,
        xanchor = "center",
        y = 1.15,
        yanchor = "top",
        showactive = TRUE,
        bgcolor = "rgba(255, 255, 255, 0.9)",
        bordercolor = "#dee2e6",
        borderwidth = 1,
        buttons = list(
          # Botón para mostrar AMBAS series
          list(
            method = "update",
            args = list(
              list(visible = c(TRUE, TRUE)),
              list(title = "<b>Serie Temporal Original y Tendencia del ETF GLTR</b>")
            ),
            label = "Mostrar Ambas"
          ),
          # Botón para mostrar solo la SERIE ORIGINAL
          list(
            method = "update",
            args = list(
              list(visible = c(TRUE, FALSE)),
              list(title = "<b>Serie Temporal Original del ETF GLTR</b>")
            ),
            label = "Solo Original"
          ),
          # Botón para mostrar solo la TENDENCIA
          list(
            method = "update",
            args = list(
              list(visible = c(FALSE, TRUE)),
              list(title = "<b>Tendencia de la Serie Temporal del ETF GLTR</b>")
            ),
            label = "Solo Tendencia"
          )
        )
      )
    ),
    # Leyenda
    legend = list(
      orientation = "h",
      x = 0.5,
      xanchor = "center",
      y = -0.15,
      font = list(
        family = "Arial, sans-serif",
        size = 13
      ),
      bgcolor = "rgba(255, 255, 255, 0.8)",
      bordercolor = "#dee2e6",
      borderwidth = 1
    )
  ) %>%
  # Información de hover personalizada
  layout(
    hoverlabel = list(
      bgcolor = "white",
      bordercolor = "#dee2e6",
      font = list(
        family = "Arial, sans-serif",
        size = 13,
        color = "#2c3e50"
      )
    )
  ) %>%
  # Añadir anotación explicativa
  add_annotations(
    text = "<i>La línea azul clara muestra los precios originales diarios. La línea roja muestra la tendencia suavizada extraída de la serie.</i>",
    x = 0.5,
    y = -0.25,
    xref = "paper",
    yref = "paper",
    xanchor = "center",
    showarrow = FALSE,
    font = list(
      family = "Arial, sans-serif",
      size = 12,
      color = "#6c757d"
    )
  )

# Mostrar el gráfico interactivo
fig_original_tendencia

La gráfica revela una tendencia claramente positiva y persistente a lo largo del período (enero 2023 - octubre 2025). La línea de tendencia suavizada muestra una trayectoria ascendente consistente, partiendo de aproximadamente &#88 USD y alcanzando alrededor de &#160 USD. La serie original oscila continuamente alrededor de la tendencia, con fluctuaciones de corto plazo que aumentan progresivamente en magnitud conforme avanza el período.

###Heatmap de estacionalidad y rendimiento El heat map visualiza los rendimientos porcentuales mensuales del ETF GLTR, permitiendo identificar patrones recurrentes estacionales.

# Asegurarse de que la columna Fecha es de tipo Date
GLTR_df <- GLTR_df %>%
  mutate(Fecha = as.Date(Fecha))

# Preparar datos para heatmap mensual
heatmap_df <- GLTR_df %>%
  filter(Fecha >= "2022-10-31" & Fecha <= "2025-10-31") %>%
  mutate(
    Año = format(Fecha, "%Y"),
    Mes_num = as.numeric(format(Fecha, "%m")),
    Mes = factor(
      Mes_num,
      levels = 1:12,
      labels = c("Ene", "Feb", "Mar", "Abr", "May", "Jun",
                 "Jul", "Ago", "Sep", "Oct", "Nov", "Dic")
    )
  ) %>%
  group_by(Año, Mes, Mes_num) %>%
  summarise(
    Precio_Inicial = first(Precio, order_by = Fecha),
    Precio_Final = last(Precio, order_by = Fecha),
    Precio_Promedio = mean(Precio, na.rm = TRUE),
    .groups = 'drop'
  ) %>%
  mutate(
    Rendimiento = ifelse(Precio_Inicial > 0, 
                         (Precio_Final - Precio_Inicial) / Precio_Inicial * 100,
                         0)
  ) %>%
  arrange(Año, Mes_num)

# Gráfico de heatmap con escala ajustada a -15% a 15%
fig_estacionalidad_heatmap <- plot_ly(
  data = heatmap_df,
  x = ~Mes,
  y = ~Año,
  z = ~Rendimiento,
  type = 'heatmap',
  colorscale = list(
    c(0, 'rgb(229, 57, 53)'),      
    c(0.5, 'rgb(244, 244, 244)'),  
    c(1, 'rgb(46, 134, 171)')      
  ),
  zmin = -15,  
  zmax = 15,   
  colorbar = list(
    title = "Rendimiento (%)",
    titleside = "right",
    tickformat = ".1f",
    len = 0.8,
    tickvals = seq(-15, 15, by = 5)  # Marcas cada 5%
  ),
  hovertemplate = paste(
    '<b>Año</b>: %{y}<br>',
    '<b>Mes</b>: %{x}<br>',
    '<b>Rendimiento</b>: %{z:.2f}%<br>',
    '<b>Precio inicial</b>: $%{text:.2f}<br>',
    '<extra></extra>'
  ),
  text = ~Precio_Inicial
) %>%
  layout(
    title = list(
      text = "<b>Heatmap de Estacionalidad Mensual - Rendimientos por Mes</b>",
      font = list(
        family = "Arial, sans-serif",
        size = 22,
        color = "#2c3e50"
      ),
      x = 0.5,
      xanchor = "center",
      y = 0.95
    ),
    xaxis = list(
      title = "<b>Mes</b>",
      titlefont = list(
        family = "Arial, sans-serif",
        size = 16,
        color = "#2c3e50"
      ),
      tickfont = list(
        family = "Arial, sans-serif",
        size = 13,
        color = "#2c3e50"
      ),
      tickangle = 0,
      showgrid = FALSE
    ),
    yaxis = list(
      title = "<b>Año</b>",
      titlefont = list(
        family = "Arial, sans-serif",
        size = 16,
        color = "#2c3e50"
      ),
      tickfont = list(
        family = "Arial, sans-serif",
        size = 13,
        color = "#2c3e50"
      ),
      autorange = "reversed",
      showgrid = FALSE,
      type = "category"
    ),
    plot_bgcolor = "rgba(255, 255, 255, 0.95)",
    paper_bgcolor = "rgba(248, 249, 250, 1)",
    margin = list(l = 80, r = 40, t = 100, b = 80),
    annotations = list(
      list(
        x = 0.5,
        y = -0.15,
        text = "<i>Cada celda muestra el rendimiento porcentual mensual. Escala: -15% a +15%. Rojo = rendimiento negativo, Azul = rendimiento positivo.</i>",
        showarrow = FALSE,
        xref = "paper",
        yref = "paper",
        xanchor = "center",
        font = list(
          family = "Arial, sans-serif",
          size = 12,
          color = "#6c757d"
        )
      )
    )
  )

# Mostrar el heatmap
fig_estacionalidad_heatmap

El heat map revela una ausencia de patrones estacionales consistentes y pronunciados en los rendimientos mensuales del ETF GLTR. A diferencia de muchos activos financieros que exhiben “efectos enero” o depresiones estacionales definidas, los rendimientos mensuales de este ETF no muestran una estructura claramente repetible año tras año. En 2022, se observa una ligera preponderancia de rendimientos negativos (tonos rosados) en febrero-marzo y mayo-junio, mientras que octubre destaca como mes de rendimiento positivo robusto. En 2023, los rendimientos mensuales son mayormente débiles o negativos (predominio de tonos pálidos y rosados), con excepción de marzo y julio que muestran un leve matiz azul. En 2024 y 2025, los patrones son aún más irregulares, con meses específicos como octubre de 2022 y octubre de 2024 mostrando rendimientos excepcionales (azul intenso), pero sin que octubre se consolide como mes sistemáticamente favorable en todos los años. El análisis identifica al mes de febrero de 2023 como el peor rendimiento histórico del ETF durante el período de entrenamiento, con una depreciación de -9.96% partiendo de un precio inicial de &#91.92 USD. En contraste, septiembre de 2025 emerge como el mejor mes, exhibiendo una apreciación robusta de +10.75% desde un precio inicial de &#149.39 USD. Esta dicotomía extrema (amplitud de 20.71 puntos porcentuales entre el peor y mejor mes) evidencia la volatilidad considerable en rendimientos mensuales, pero el hecho de que estos extremos ocurren en meses diferentes (febrero y septiembre) y en años distantes refuerza la conclusión de que no existe un efecto estacional genuino y replicable que privilegie o penalice sistemáticamente meses específicos.

###Bandas de volatilidad

Las bandas visualizan la evolución dinámica de la volatilidad, superponiendo el precio de cierre diario, la media y las bandas que se expanden o contraen según la desviación estándar.

# Calcular medias móviles y bandas de volatilidad
volatilidad_df <- GLTR_df %>%
  arrange(Fecha) %>%
  mutate(
    Media_Movil_20 = SMA(Precio, n = 20),
    Desviacion_20 = runSD(Precio, n = 20),
    Banda_Superior = Media_Movil_20 + (2 * Desviacion_20),
    Banda_Inferior = Media_Movil_20 - (2 * Desviacion_20),
    Ancho_Banda = Banda_Superior - Banda_Inferior
  )

# Gráfico elegante de bandas de volatilidad
fig_bandas <- plot_ly(volatilidad_df, x = ~Fecha) %>%
  # Área entre bandas (volatilidad) - SOLO MUESTRA ANCHO
  add_ribbons(
    ymin = ~Banda_Inferior,
    ymax = ~Banda_Superior,
    name = 'Banda de Volatilidad',
    fillcolor = 'rgba(46, 134, 171, 0.15)',
    line = list(color = 'transparent'),
    hovertemplate = 'Ancho: $%{customdata:.2f}<extra></extra>',
    customdata = ~Ancho_Banda  # Solo muestra el ancho de banda
  ) %>%
  # Línea de precio
  add_trace(
    y = ~Precio, 
    type = 'scatter', 
    mode = 'lines',
    name = 'Precio GLTR',
    line = list(color = '#2c3e50', width = 1.5),
    hovertemplate = 'Precio: $%{y:.2f}<extra></extra>'
  ) %>%
  # Media móvil
  add_trace(
    y = ~Media_Movil_20, 
    type = 'scatter', 
    mode = 'lines',
    name = 'Media Móvil 20 días',
    line = list(color = '#FF6F61', width = 2, dash = 'dash'),
    hovertemplate = 'Media 20d: $%{y:.2f}<extra></extra>'
  ) %>%
  layout(
    title = list(
      text = "<b>Bandas de Volatilidad del ETF GLTR</b><br><sub>Las bandas se expanden en periodos de alta volatilidad y se contraen en calma</sub>",
      font = list(family = "Arial", size = 20)
    ),
    xaxis = list(
      title = "Fecha",
      rangeslider = list(visible = FALSE),
      showgrid = TRUE,
      gridcolor = 'rgba(200,200,200,0.1)'
    ),
    yaxis = list(
      title = "Precio (USD)",
      tickformat = "$.2f",
      gridcolor = 'rgba(200,200,200,0.1)'
    ),
    plot_bgcolor = '#ffffff',
    paper_bgcolor = '#f8f9fa',
    hovermode = 'x unified',
    legend = list(
      orientation = "h",
      x = 0.5,
      xanchor = "center",
      y = -0.15
    ),
    updatemenus = list(
      list(
        type = "buttons",
        direction = "right",
        x = 0.3,
        y = 1.15,
        buttons = list(
          list(
            method = "restyle",
            args = list("visible", c(TRUE, TRUE, TRUE)),
            label = "Mostrar Todo"
          ),
          list(
            method = "restyle",
            args = list("visible", c(TRUE, TRUE, FALSE)),
            label = "Ocultar Media"
          ),
          list(
            method = "restyle",
            args = list("visible", c(TRUE, FALSE, TRUE)),
            label = "Ocultar Precio"
          )
        )
      )
    )
  )

fig_bandas

La gráfica exhibe expansión consistente del ancho de las bandas conforme avanza el tiempo. Durante 2023, las bandas son extremadamente estrechas (±&#4-6 USD), reflejando volatilidad baja. A partir de enero de 2024, el ancho aumenta considerablemente, alcanzando ±&#10-12 USD para mediados de año. En 2025, la expansión es dramática, alcanzando un ancho máximo de aproximadamente &#38 USD—el pico de volatilidad del período. Un patrón notable es que la expansión de volatilidad acompaña la trayectoria ascendente del precio. En períodos donde el precio se estanca (2023 con precios cercanos a &#85-95 USD), las bandas permanecen estrechas. Conforme el precio asciende hacia &#100-120 USD en 2024 y luego hacia &#140-190 USD en 2025, las bandas se expanden paralelamente. Esto sugiere que la volatilidad no es independiente del nivel de precio, sino que ambas dimensiones están co-determinadas por factores macroeconómicos comunes que impulsan tanto la apreciación como la incertidumbre en los precios de metales preciosos.

###Volatilidad comparada en rangos de tiempo

La visualización de volatilidad en múltiples ventanas temporales (5 días, 20 días, 60 días y anual) permite caracterizar la estructura multiescalar de la variabilidad del ETF GLTR, identificando cómo los shocks y la incertidumbre operan en distintos horizontes temporales.

# Calcular volatilidad en diferentes ventanas temporales
comparador_volatilidad <- GLTR_df %>%
  arrange(Fecha) %>%
  mutate(
    Rendimiento = (Precio / lag(Precio) - 1) * 100
  ) %>%
  filter(!is.na(Rendimiento)) %>%
  mutate(
    Vol_5d = rollapply(Rendimiento, width = 5, FUN = sd, fill = NA, align = "right"),
    Vol_20d = rollapply(Rendimiento, width = 20, FUN = sd, fill = NA, align = "right"),
    Vol_60d = rollapply(Rendimiento, width = 60, FUN = sd, fill = NA, align = "right"),
    Vol_252d = rollapply(Rendimiento, width = 252, FUN = sd, fill = NA, align = "right")
  )

# Gráfico comparativo elegante
fig_comparativo <- plot_ly(comparador_volatilidad, x = ~Fecha) %>%
  # Volatilidad a 5 días (corto plazo)
  add_trace(
    y = ~Vol_5d,
    type = 'scatter',
    mode = 'lines',
    name = 'Vol 5 días',
    line = list(color = '#9fa0ff', width = 1.5),
    visible = TRUE,
    hovertemplate = 'Vol 5d: %{y:.2f}%<extra></extra>'
  ) %>%
  # Volatilidad a 20 días
  add_trace(
    y = ~Vol_20d,
    type = 'scatter',
    mode = 'lines',
    name = 'Vol 20 días',
    line = list(color = '#2E86AB', width = 2),
    visible = TRUE,
    hovertemplate = 'Vol 20d: %{y:.2f}%<extra></extra>'
  ) %>%
  # Volatilidad a 60 días
  add_trace(
    y = ~Vol_60d,
    type = 'scatter',
    mode = 'lines',
    name = 'Vol 60 días',
    line = list(color = '#ada7ff', width = 2.5),
    visible = TRUE,
    hovertemplate = 'Vol 60d: %{y:.2f}%<extra></extra>'
  ) %>%
  # Volatilidad a 252 días (anualizada)
  add_trace(
    y = ~Vol_252d,
    type = 'scatter',
    mode = 'lines',
    name = 'Vol Anual',
    line = list(color = '#757bc8', width = 3),
    visible = TRUE,
    hovertemplate = 'Vol Anual: %{y:.2f}%<extra></extra>'
  ) %>%
  layout(
    title = list(
      text = "<b>Comparativo de Volatilidad en Diferentes Ventanas Temporales</b>",
      font = list(family = "Arial", size = 20)
    ),
    xaxis = list(
      title = "Fecha",
      showgrid = TRUE,
      gridcolor = 'rgba(200,200,200,0.1)'
    ),
    yaxis = list(
      title = "Volatilidad (% desviación estándar)",
      tickformat = ".1f",
      gridcolor = 'rgba(200,200,200,0.1)'
    ),
    plot_bgcolor = '#ffffff',
    paper_bgcolor = '#f8f9fa',
    hovermode = 'x unified',
    legend = list(
      orientation = "h",
      x = 0.5,
      xanchor = "center",
      y = -0.15
    ),
    updatemenus = list(
      list(
        type = "buttons",
        direction = "right",
        x = 0.3,
        y = 1.15,
        showactive = TRUE,
        buttons = list(
          list(
            method = "restyle",
            args = list("visible", rep(TRUE, 4)),
            label = "Mostrar Todas"
          ),
          list(
            method = "restyle",
            args = list("visible", c(TRUE, FALSE, FALSE, FALSE)),
            label = "Solo 5 días"
          ),
          list(
            method = "restyle",
            args = list("visible", c(FALSE, TRUE, FALSE, FALSE)),
            label = "Solo 20 días"
          ),
          list(
            method = "restyle",
            args = list("visible", c(FALSE, FALSE, TRUE, FALSE)),
            label = "Solo 60 días"
          ),
          list(
            method = "restyle",
            args = list("visible", c(FALSE, FALSE, FALSE, TRUE)),
            label = "Solo Anual"
          )
        )
      )
    )
  )

# Mostrar el gráfico
fig_comparativo

La volatilidad de Corto Plazo exhibe fluctuaciones erráticas y de alta amplitud, oscilando entre aproximadamente 0.5% y 4.0%. Esta serie es notoriamente ruidosa, con múltiples picos transitorios que reflejan shocks diarios rápidamente absorbidos por el mercado.

La volatilidad de Mediano Plazo presenta un patrón mucho más suave que la de 5 días, oscilando típicamente entre 0.8% y 2.0%. La línea azul filtra el ruido diario y captura la variabilidad subyacente de corto-mediano plazo, con picos menos frecuentes pero más persistentes.

La volatilidad de Largo Plazo muestra la trayectoria más suave y persistente, fluctuando entre aproximadamente 0.8% y 1.5%. Las oscilaciones en esta ventana son lentas y deliberadas, reflejando cambios en el ambiente macroeconómico de mediano plazo.

La volatilidad Anual proporciona la perspectiva más agregada, con una evolución particularmente estable, comenzando cercana a 1.0% en 2023 y terminando cercana a 1.5-1.8% en 2025.

El análisis descriptivo ha caracterizado la serie temporal del ETF GLTR a través de sus estadísticas fundamentales, distribución temporal, tendencia, estacionalidad y dinámica de volatilidad en múltiples horizontes. Esta exploración integral proporciona la base empírica necesaria para proceder con la especificación y estimación del modelo ARIMA.

3.2 Descomposición STL

decomp <- stl(serie_ts, s.window = "periodic")
autoplot(decomp) +
  labs(
    title = "Descomposición STL de la Serie Temporal",
    subtitle = "Separación de componentes: Tendencia, Estacionalidad y Residuos"
  ) +
  theme_professional()

4 Análisis ARIMA

4.1 Verificación de Estacionariedad

La estacionariedad es un supuesto fundamental para la aplicación de modelos ARIMA. Evaluaremos este requisito mediante pruebas estadísticas formales.

adf_result <- adf.test(serie_ts)
kpss_result <- kpss.test(serie_ts)

cat("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cat("TEST ADF (Augmented Dickey-Fuller)\n")
## TEST ADF (Augmented Dickey-Fuller)
cat("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cat(sprintf("Estadístico:  %.6f\n", adf_result$statistic))
## Estadístico:  0.569251
cat(sprintf("p-valor:      %.6f\n", adf_result$p.value))
## p-valor:      0.990000
cat(sprintf("Lag Order:    %d\n", adf_result$parameter))
## Lag Order:    9
cat("\nHipótesis H0: Serie tiene raíz unitaria (no estacionaria)\n")
## 
## Hipótesis H0: Serie tiene raíz unitaria (no estacionaria)
cat("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
## 
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cat("TEST KPSS (Kwiatkowski-Phillips-Schmidt-Shin)\n")
## TEST KPSS (Kwiatkowski-Phillips-Schmidt-Shin)
cat("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cat(sprintf("Estadístico:  %.6f\n", kpss_result$statistic))
## Estadístico:  8.954529
cat(sprintf("p-valor:      %.6f\n", kpss_result$p.value))
## p-valor:      0.010000
cat("\nHipótesis H0: Serie es estacionaria\n")
## 
## Hipótesis H0: Serie es estacionaria

4.2 Funciones de Autocorrelación

par(mfrow = c(1, 2), 
    bg = "white",
    col.main = "#1a365d", 
    col.lab = "#4a5568", 
    col.axis = "#4a5568",
    fg = "#4a5568",
    family = "serif")

acf(serie_ts, 
    main = "ACF - Función de Autocorrelación",
    col = "#2b6cb0",
    lwd = 2)

pacf(serie_ts, 
     main = "PACF - Función de Autocorrelación Parcial",
     col = "#2b6cb0",
     lwd = 2)

par(mfrow = c(1, 1))

4.3 Selección del Modelo

modelo_auto <- auto.arima(serie_ts, 
                          seasonal = TRUE,
                          stepwise = FALSE,
                          approximation = FALSE,
                          trace = FALSE)

cat("MODELO ARIMA AUTOMÁTICO SELECCIONADO\n")
## MODELO ARIMA AUTOMÁTICO SELECCIONADO
cat("════════════════════════════════════════\n")
## ════════════════════════════════════════
cat(sprintf("Orden (p,d,q): (%d,%d,%d)\n", 
            modelo_auto$arma[1], 
            modelo_auto$arma[6], 
            modelo_auto$arma[2]))
## Orden (p,d,q): (5,2,0)
cat(sprintf("AIC:  %.2f\n", AIC(modelo_auto)))
## AIC:  3594.69
cat(sprintf("BIC:  %.2f\n", BIC(modelo_auto)))
## BIC:  3624.03
cat("════════════════════════════════════════\n")
## ════════════════════════════════════════

4.4 Comparación de Modelos

modelos <- list(
  "ARIMA(1,1,1)" = arima(serie_ts, order = c(1, 1, 1)),
  "ARIMA(2,1,0)" = arima(serie_ts, order = c(2, 1, 0)),
  "ARIMA(0,1,2)" = arima(serie_ts, order = c(0, 1, 2)),
  "ARIMA Automático" = modelo_auto
)

comparacion <- data.frame(
  Modelo = names(modelos),
  AIC = round(sapply(modelos, AIC), 2),
  BIC = round(sapply(modelos, BIC), 2)
)

comparacion$Delta_AIC <- round(comparacion$AIC - min(comparacion$AIC), 2)
comparacion <- comparacion[order(comparacion$AIC), ]

kable(comparacion,
      caption = "Tabla 2: Comparación de Modelos ARIMA",
      col.names = c("Modelo", "AIC", "BIC", "Δ AIC"),
      align = c("l", "r", "r", "r")) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover"),
    full_width = FALSE,
    position = "center"
  ) %>%
  row_spec(0, background = "#1a365d", color = "white", bold = TRUE) %>%
  row_spec(1, background = "#e6f0ff", bold = TRUE)
Tabla 2: Comparación de Modelos ARIMA
Modelo AIC BIC Δ AIC
ARIMA(0,1,2) ARIMA(0,1,2) 3453.31 3467.98 0.00
ARIMA(2,1,0) ARIMA(2,1,0) 3454.00 3468.67 0.69
ARIMA(1,1,1) ARIMA(1,1,1) 3455.87 3470.54 2.56
ARIMA Automático ARIMA Automático 3594.69 3624.03 141.38

4.5 Diagnóstico de Residuos

checkresiduals(modelo_auto)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(5,2,0)
## Q* = 224.38, df = 192, p-value = 0.05465
## 
## Model df: 5.   Total lags used: 197
lb_test <- Box.test(residuals(modelo_auto), 
                    lag = 20, 
                    type = "Ljung-Box")

cat("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
## 
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cat("TEST DE LJUNG-BOX - Independencia de Residuos\n")
## TEST DE LJUNG-BOX - Independencia de Residuos
cat("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cat(sprintf("Estadístico Q: %.4f\n", lb_test$statistic))
## Estadístico Q: 66.5625
cat(sprintf("p-valor:       %.4f\n", lb_test$p.value))
## p-valor:       0.0000
cat("Hipótesis H0:  Residuos son ruido blanco (independientes)\n")
## Hipótesis H0:  Residuos son ruido blanco (independientes)
if(lb_test$p.value > 0.05) {
  cat("\n✓ RESULTADO: Los residuos satisfacen el supuesto de independencia\n")
} else {
  cat("\n✗ RESULTADO: Evidencia de autocorrelación residual\n")
}
## 
## ✗ RESULTADO: Evidencia de autocorrelación residual

5 Pronósticos

5.1 Visualización de Pronósticos

pronostico <- forecast(modelo_auto, h = 24)

autoplot(pronostico) +
  labs(
    title = "Pronóstico ARIMA de la Serie Temporal",
    subtitle = "Período histórico + 24 meses de proyección con intervalos de confianza",
    y = "Valor",
    x = "Tiempo"
  ) +
  theme_professional() +
  theme(
    legend.position = "top",
    legend.title = element_blank(),
    plot.title = element_text(size = 16)
  )

5.2 Tabla de Pronósticos

df_pronostico <- data.frame(
  Período = seq(1, 24),
  Pronóstico = round(as.numeric(pronostico$mean), 2),
  LI_80 = round(as.numeric(pronostico$lower[, 1]), 2),
  LS_80 = round(as.numeric(pronostico$upper[, 1]), 2),
  LI_95 = round(as.numeric(pronostico$lower[, 2]), 2),
  LS_95 = round(as.numeric(pronostico$upper[, 2]), 2)
)

kable(head(df_pronostico, 12),
      caption = "Tabla 3: Pronósticos para los Próximos 12 Períodos",
      col.names = c("Período", "Pronóstico", "LI 80%", "LS 80%", "LI 95%", "LS 95%"),
      align = c("c", "r", "r", "r", "r", "r")) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover"),
    full_width = FALSE,
    position = "center"
  ) %>%
  row_spec(0, background = "#1a365d", color = "white", bold = TRUE)
Tabla 3: Pronósticos para los Próximos 12 Períodos
Período Pronóstico LI 80% LS 80% LI 95% LS 95%
1 189.96 188.03 191.88 187.01 192.90
2 191.93 189.04 194.83 187.50 196.37
3 193.68 189.77 197.59 187.70 199.65
4 194.92 189.93 199.91 187.29 202.55
5 196.04 189.96 202.12 186.73 205.34
6 197.33 189.95 204.70 186.05 208.61
7 198.80 189.99 207.61 185.33 212.27
8 200.28 190.00 210.56 184.55 216.01
9 201.68 189.85 213.51 183.59 219.77
10 203.01 189.58 216.45 182.47 223.56
11 204.36 189.25 219.47 181.25 227.46
12 205.74 188.88 222.61 179.95 231.53

6 Conclusiones

6.1 Hallazgos Principales

El análisis ARIMA realizado permite caracterizar la serie temporal mediante la identificación de su estructura de autocorrelación, estacionariedad y componentes de tendencia y estacionalidad. Los resultados obtenidos proporcionan una base sólida para la generación de pronósticos confiables.

📌 Síntesis de Hallazgos:

  • La serie presenta componentes de tendencia y estacionalidad claros
  • El modelo seleccionado captura adecuadamente la estructura temporal
  • Los pronósticos generados mantienen intervalos de confianza razonables
  • La validación de residuos indica un buen ajuste del modelo

6.2 Implicaciones y Recomendaciones

Los pronósticos obtenidos pueden utilizarse para:

  • Planificación estratégica a corto y mediano plazo
  • Asignación eficiente de recursos
  • Identificación de desviaciones significativas
  • Apoyo en la toma de decisiones basada en evidencia

⚠️ Limitaciones Metodológicas:

  • Los pronósticos pierden precisión en horizontes muy lejanos
  • Cambios estructurales no capturados afectarían la predicción
  • La calidad de los datos es fundamental para la confiabilidad
  • Validación con datos nuevos es recomendada

7 Referencias Bibliográficas